#include <Windows.h>

#include <iostream>


DWORD WINAPI EventThread(LPVOID lpThreadParameter)
{
    HANDLE hEvent = (HANDLE)lpThreadParameter;
    printf("[Debug] ThreadRoutine Start\r\n");
    Sleep(1000);
    SetEvent(hEvent);
    printf("[Debug] ThreadRoutine End\r\n");
    return 0;
}

void Event()
{
    HANDLE hEvent;
    HANDLE hThread;

    hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    if (!hEvent)
    {
        printf("[Error] CreateEvent Error=%#X\r\n", GetLastError());
        return;
    }

    hThread = CreateThread(NULL, 0, EventThread, hEvent, 0, NULL);
    if (!hThread)
    {
        printf("[Error] CreateThread Error=%#X\r\n", GetLastError());
        return;
    }
    printf("[Debug] Event Wait\r\n");
    WaitForSingleObject(hEvent, INFINITE);
    printf("[Debug] Event End\r\n");
}

DWORD WINAPI SemaphoreThread(LPVOID lpThreadParameter)
{
    HANDLE hSemaphore = (HANDLE)lpThreadParameter;
    printf("[Debug] SemaphoreThread Start\r\n");
    Sleep(1000);
    ReleaseSemaphore(hSemaphore, 1, NULL);
    printf("[Debug] SemaphoreThread End\r\n");
    return 0;
}

void Semaphore()
{
    HANDLE hSemaphore;
    LONG count = 0;

    hSemaphore = CreateSemaphore(NULL, 2, 2, NULL);
    if (!hSemaphore)
    {
        printf("[Error] CreateSemaphore Error=%#X\r\n", GetLastError());
        return;
    }
    WaitForSingleObject(hSemaphore, INFINITE);
    WaitForSingleObject(hSemaphore, INFINITE);
    CreateThread(NULL, 0, SemaphoreThread, hSemaphore, 0, NULL);
    printf("[Debug] Semaphore Wait\r\n");
    WaitForSingleObject(hSemaphore, INFINITE);
    printf("[Debug] Semaphore End\r\n");
}



DWORD MutexThread1(LPVOID lpThreadParameter)
{
    HANDLE hMutex = (HANDLE)lpThreadParameter;
    printf("[Debug] MutexThread1 Start\r\n");
    WaitForSingleObject(hMutex, INFINITE);
    WaitForSingleObject(hMutex, INFINITE);
    printf("[Debug] MutexThread1 Sleep\r\n");
    Sleep(1000);
    ReleaseMutex(hMutex);
    printf("[Debug] MutexThread1 End\r\n");
    return 0;
}

DWORD MutexThread2(LPVOID lpThreadParameter)
{
    HANDLE hMutex = (HANDLE)lpThreadParameter;
    printf("[Debug] MutexThread2 Start\r\n");
    WaitForSingleObject(hMutex, INFINITE);
    printf("[Debug] MutexThread2 Sleep\r\n");
    Sleep(1000);
    ReleaseMutex(hMutex);
    printf("[Debug] MutexThread2 End\r\n");
    return 0;
}

VOID Mutex()
{
    HANDLE hMutex;
    HANDLE hThreads[2];

    hMutex = CreateMutex(NULL, FALSE, NULL);
    if (!hMutex)
    {
        printf("[Error] CreateMutex Error=%#X\r\n", GetLastError());
        return;
    }
    hThreads[0] = CreateThread(NULL, 0, MutexThread1, hMutex, 0, NULL);
    hThreads[1] = CreateThread(NULL, 0, MutexThread2, hMutex, 0, NULL);
    WaitForMultipleObjects(sizeof(hThreads)/sizeof(hThreads[0]), hThreads, TRUE, INFINITE);
    printf("[Debug] Mutex End\r\n");
}

int main(int argc, char **argv)
{
    // Event();
    // Semaphore();
    Mutex();


    return 0;
}